﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="PhysicalMedia.cs" company="Data Ductus Malmö">
//   (c) 2010 - 2012 Data Ductus Malmö AB
// </copyright>
// --------------------------------------------------------------------------------------------------------------------

namespace DataDuctus.Snmp.Persistor.Core.Types
{
  using System;
  using System.ComponentModel;
  using System.Globalization;

  using Lextm.SharpSnmpLib;

  /// <summary>
  /// As per RFC1155-SMI.
  /// </summary>
  /// <remarks>
  /// PhysAddress ::=
  ///               OCTET STRING
  ///           -- This data type is used to model media addresses.  For many
  ///           -- types of media, this will be in a binary representation.
  ///           -- For example, an ethernet address would be represented as
  ///           -- a string of 6 octets.
  /// </remarks>
  public sealed class PhysicalMedia : TypeConverter
  {
    #region Public Methods and Operators

    /// <summary>
    /// The can convert from.
    /// </summary>
    /// <param name="context">
    /// The context.
    /// </param>
    /// <param name="sourceType">
    /// The source type.
    /// </param>
    /// <returns>
    /// The System.Boolean.
    /// </returns>
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
      if (sourceType == typeof(OctetString))
      {
        return true;
      }

      return base.CanConvertFrom(context, sourceType);
    }

    /// <summary>
    /// The can convert to.
    /// </summary>
    /// <param name="context">
    /// The context.
    /// </param>
    /// <param name="destinationType">
    /// The destination type.
    /// </param>
    /// <returns>
    /// The System.Boolean.
    /// </returns>
    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    {
      if (destinationType == typeof(string))
      {
        return true;
      }

      return base.CanConvertTo(context, destinationType);
    }

    /// <summary>
    /// The convert from.
    /// </summary>
    /// <param name="context">
    /// The context.
    /// </param>
    /// <param name="culture">
    /// The culture.
    /// </param>
    /// <param name="value">
    /// The value.
    /// </param>
    /// <returns>
    /// The System.Object.
    /// </returns>
    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
      if (!(value is string))
      {
        return base.ConvertFrom(context, culture, value);
      }

      string[] components = ((string)value).Split(':');

      var data = new byte[6];

      for (int i = 0; i < 6; i++)
      {
        data[i] = Convert.ToByte(components[i], 16);
      }

      return new OctetString(data);
    }

    /// <summary>
    /// The convert to.
    /// </summary>
    /// <param name="context">
    /// The context.
    /// </param>
    /// <param name="culture">
    /// The culture.
    /// </param>
    /// <param name="value">
    /// The value.
    /// </param>
    /// <param name="destinationType">
    /// The destination type.
    /// </param>
    /// <returns>
    /// The System.Object.
    /// </returns>
    public override object ConvertTo(
      ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
    {
      if (!(value is OctetString) || (destinationType != typeof(string)))
      {
        return base.ConvertTo(context, culture, value, destinationType);
      }

      byte[] data = ((OctetString)value).GetRaw();

      if (6 != data.Length)
      {
        return base.ConvertTo(context, culture, value, destinationType);
      }

      return string.Format(
        "{0}:{1}:{2}:{3}:{4}:{5}", 
        data[0].ToString("X2"), 
        data[1].ToString("X2"), 
        data[2].ToString("X2"), 
        data[3].ToString("X2"), 
        data[4].ToString("X2"), 
        data[5].ToString("X2"));
    }

    #endregion
  }
}